/* eslint camelcase:0 */
import React from 'react';
import PropTypes from 'prop-types';
import cn from 'classnames';
import Joi from 'joi';
import { useForm } from 'react-hook-form';
import { joiResolver } from '@hookform/resolvers';
import { Link } from 'react-router-dom';
import { Select } from 'antd';
import { gql, useQuery } from '@apollo/client';

import Button from '@kuiper-components/button';
import Dialog from '@kuiper-components/dialog';
import Input from '@kuiper-components/input';
import CheckboxGroup from '../../../../../components/CheckboxGroup';
import Helper from '../../../../../components/Helper';
import Form, { Field } from '../../../../../components/Form';
import LabeledComponent from '../../../../../components/LabeledComponent';
import NameTargetSelect from './NameTargetSelect';
import { INFORM_OPTIONS } from '../../../../../../common/constants';

import s from './Edit.module.css';
const ALERT_GROUP_QUERY = gql`
	{
		AlertGroupMany {
			isDefault
			receiverIds
			name
			_id
		}
	}
`;

const nameTargetFilter = {
	cydEnabled: true,
	verification: { isVerified: true },
	_operators: { target: { port: { in: [null, 80, 443] } } },
};
const validateSchema = joiResolver(
	Joi.object({
		job_id: Joi.string().required().messages({
			'string.empty': '请选择资产',
			'any.required': '请选择资产',
		}),
		alertGroupIds: Joi.array(),
		notification: Joi.object(),
		note: Joi.string(),
		targetUrl: Joi.string(),
		settings: Joi.object({
			securityEvent: Joi.object({
				foreign_links: Joi.number()
					.default(0)
					.min(0)
					.messages({ 'number.min': '不能小于0' }),
				black_links: Joi.number()
					.default(0)
					.min(0)
					.messages({ 'number.min': '不能小于0' }),
				broken_links: Joi.number()
					.default(0)
					.min(0)
					.messages({ 'number.min': '不能小于0' }),
				cryjack: Joi.boolean().default(false),
				malscan: Joi.boolean().default(false),
			}),
			vul: Joi.object({
				critical: Joi.number()
					.default(0)
					.min(0)
					.messages({ 'number.min': '不能小于0' }),
				high: Joi.number()
					.default(0)
					.min(0)
					.messages({ 'number.min': '不能小于0' }),
				low: Joi.number()
					.default(0)
					.min(0)
					.messages({ 'number.min': '不能小于0' }),
				medium: Joi.number()
					.default(0)
					.min(0)
					.messages({ 'number.min': '不能小于0' }),
			}),
		}),
	})
);

function Edit({
	className,
	children,
	value,
	visible: visibleProp,
	jobIdSelectDisabled,
	onChange,
	onSubmit,
}) {
	const { data: groupData } = useQuery(ALERT_GROUP_QUERY);
	const { Option } = Select;
	const form = useForm({
		defaultValues: value,
		resolver: validateSchema,
		reValidateMode: 'onBlur',
	});
	const titleTipRef = React.useRef(null);
	const strategyTipRef = React.useRef(null);
	const [visibleState, setVisible] = React.useState(visibleProp);
	const visible = visibleProp === undefined ? visibleState : visibleProp;
	const handleOpoen = () => {
		setVisible(true);
		onChange(true);
	};
	const handleClose = () => {
		setVisible(false);
		onChange(false);
	};

	const [submitLoading, setSubmitLoading] = React.useState(false);
	const handleSubmit = values => {
		setSubmitLoading(true);
		return onSubmit({ ...values, settingId: value._id })
			.then(handleClose)
			.finally(() => setSubmitLoading(false));
	};
	const numData = form.watch([
		'settings.vul.critical',
		'settings.vul.high',
		'settings.vul.medium',
		'settings.vul.low',
		'settings.securityEvent.black_links',
		'settings.securityEvent.foreign_links',
	]);
	Object.entries(numData).forEach(([key, val]) => {
		if (val > 999) {
			form.setValue(key, 999);
		}
	});
	React.useEffect(() => {
		setTimeout(() => {
			if (!value.alertGroupIds[0] && groupData) {
				form.setValue(`alertGroupIds`, [groupData.AlertGroupMany[0]._id]);
			}
		}, 1000);
	}, [visible, groupData]);
	return (
		<>
			{React.cloneElement(children, {
				...children.props,
				className: cn(className, s.edit),
				onClick: handleOpoen,
			})}
			<Dialog
				destroyOnClose
				title={
					<span ref={titleTipRef} className={s.dialogTitle}>
						{value?.job_id ? '修改策略' : '添加策略'}
						<Helper
							placement="top"
							overlay="ScanV将对满足以下策略条件的URL在云防御平台一键加黑，请谨慎操作。当前仅支持443及80端口服务。"
							getTooltipContainer={() => titleTipRef.current}
						/>
					</span>
				}
				visible={visible}
				prefixCls={s.dialog}
				onClose={handleClose}
			>
				<Form className={s.form} form={form} onSubmit={handleSubmit}>
					<Field
						className={s.jobIdSelectField}
						componentClassName={s.jobIdSelect}
						name="job_id"
						as={NameTargetSelect}
						filter={nameTargetFilter}
						disabled={jobIdSelectDisabled}
						required
					/>
					<div className={s.urlStrategy}>
						<span className={s.fieldName}>URL满足策略:</span>
						<div className={s.strategySettings} ref={strategyTipRef}>
							<div className={s.row}>
								<span className={s.strategySettingName}>安全漏洞:</span>
								<Field
									className={s.item}
									name="settings.vul.critical"
									as={LabeledComponent}
									before="严重"
									after="个"
								>
									<Input className={s.num} type="number" min="0" />
								</Field>
								<Field
									className={s.item}
									name="settings.vul.high"
									as={LabeledComponent}
									before="高危"
									after="个"
								>
									<Input className={s.num} type="number" min="0" />
								</Field>
								<Field
									className={s.item}
									name="settings.vul.medium"
									as={LabeledComponent}
									before="中危"
									after="个"
								>
									<Input className={s.num} type="number" min="0" />
								</Field>
								<Field
									className={s.item}
									name="settings.vul.low"
									as={LabeledComponent}
									before="低危"
									after="个"
								>
									<Input className={s.num} type="number" min="0" />
								</Field>
							</div>
							<div className={s.row}>
								<span className={s.strategySettingName}>安全事件:</span>
								<Field
									className={s.item}
									name="settings.securityEvent.black_links"
									as={LabeledComponent}
									before="暗链"
									after="个"
								>
									<Input className={s.num} type="number" min="0" />
								</Field>
								<Field
									className={s.item}
									name="settings.securityEvent.foreign_links"
									as={LabeledComponent}
									before="风险外链"
									after="个"
								>
									<Input className={s.num} type="number" min="0" />
								</Field>
								<Field
									className={s.item}
									name="settings.securityEvent.cryjack"
									render={({ value, onChange, onBlur }) => (
										<label className={s.checkboxContainer}>
											<Input
												className={s.checkbox}
												type="checkbox"
												checked={value}
												onChange={onChange}
												onBlur={onBlur}
											/>
											挖矿
										</label>
									)}
								/>
								<Field
									className={s.item}
									name="settings.securityEvent.malscan"
									render={({ value, onChange, onBlur }) => (
										<label className={s.checkboxContainer}>
											<Input
												className={s.checkbox}
												type="checkbox"
												checked={value}
												onChange={onChange}
												onBlur={onBlur}
											/>
											挂马
										</label>
									)}
								/>
							</div>
						</div>
						<Helper
							className={s.tip}
							placement="top"
							overlay="安全漏洞和安全事件内部条件按“并”关系生效；安全漏洞和安全事件之间按“或”关系生效。"
							getTooltipContainer={() => strategyTipRef.current}
						/>
					</div>
					<div className={s.informBox}>
						<span>告警通知:</span>
						<div>
							<div className={s.fieldInfo}>
								<Field
									className={s.fieldLabel}
									label="通知对象"
									name="alertGroupIds"
									render={({ value, onChange, onBlur }) => (
										<Select
											className={s.select}
											optionFilterProp="children"
											placeholder="请选择"
											value={value}
											onBlur={onBlur}
											onChange={onChange}
											mode="multiple"
											getPopupContainer={triggerNode => triggerNode}
										>
											{groupData
												? groupData.AlertGroupMany.map(item => (
														<Option key={item._id} value={item._id}>
															{item.name}
														</Option>
												  ))
												: null}
										</Select>
									)}
								/>
								<Link to="/alert/settings/alert-group" className={s.alertLink}>
									创建告警策略
								</Link>
							</div>

							<Field
								labelClassName={s.fieldLabel}
								label="通知类型"
								name="notification"
								componentClassName={s.alertSelect}
								render={({ onChange, onBlur, value }) => {
									return (
										<CheckboxGroup
											checkboxClassName={s.checkboxN}
											onChange={onChange}
											onBlur={onBlur}
											checked={value}
											options={INFORM_OPTIONS}
										/>
									);
								}}
							/>
						</div>
					</div>
					<mark className={s.note} data-type="warning">
						注：请确保该资产在云防御平台处于云端防护状态，若回源状态，添加的URL黑名单将不生效。
					</mark>
					<div className={s.footer}>
						<Button onClick={handleClose}>取消</Button>
						<Button primary type="submit" loading={submitLoading}>
							{value?.job_id ? '保存' : '添加'}
						</Button>
					</div>
				</Form>
			</Dialog>
		</>
	);
}

Edit.propTypes = {
	className: PropTypes.string,
	children: PropTypes.node,
	visible: PropTypes.bool,
	jobIdSelectDisabled: PropTypes.bool,
	value: PropTypes.shape({
		_id: PropTypes.string,
		job_id: PropTypes.string,
		is_alert: PropTypes.bool,
		note: PropTypes.string,
		targetUrl: PropTypes.string,
		settings: PropTypes.shape({
			securityEvent: PropTypes.shape({
				black_links: PropTypes.number,
				broken_links: PropTypes.number,
				cryjack: PropTypes.bool,
				malscan: PropTypes.bool,
			}),
			vul: PropTypes.shape({
				critical: PropTypes.number,
				high: PropTypes.number,
				low: PropTypes.number,
				medium: PropTypes.number,
			}),
		}),
		alertGroupIds: PropTypes.any,
		notification: PropTypes.any,
	}),
	onChange: PropTypes.func,
	onSubmit: PropTypes.func.isRequired,
};

Edit.defaultProps = {
	className: s.edit,
	jobIdSelectDisabled: false,
	value: {
		is_alert: false,
		job_id: undefined,
		targetUrl: '',
		note: '',
		settings: {
			securityEvent: {
				black_links: 0,
				broken_links: 0,
				foreign_links: 0,
				cryjack: false,
				malscan: false,
			},
			vul: {
				critical: 0,
				high: 0,
				low: 0,
				medium: 0,
			},
		},
		alertGroupIds: [],
		notification: {
			email: true,
			sms: true,
			wechat: true,
			inBox: true,
		},
	},
	onChange: () => {},
};

export default Edit;
